package ast

import (
	"fmt"
	"strconv"
	"strings"

	"gitee.com/u-language/u-language/ucom/astdata"
	"gitee.com/u-language/u-language/ucom/data"
	"gitee.com/u-language/u-language/ucom/enum"
	"gitee.com/u-language/u-language/ucom/internal/utils"
)

var _ Node = (*VarNode)(nil)
var _ Node = (*FuncNode)(nil)
var _ Node = (*ASSIGNNode)(nil)
var _ Node = (*Object)(nil)
var _ Expr = (*OpExpr)(nil)

// var _ Node = (*BlankLineNode)(nil)
var _ Node = (*RbraceNode)(nil)
var _ Node = (*IfNode)(nil)
var _ Node = (*ElseNode)(nil)

// var _ Node = (*MLCStartNode)(nil)
// var _ Node = (*MLCEndNode)(nil)
// var _ Node = (*MLCInNode)(nil)
var _ Node = (*ForNode)(nil)
var _ Node = (*CallNode)(nil)
var _ Node = (*ReturnNode)(nil)
var _ Node = (*GotoStmt)(nil)
var _ Node = (*LabelNode)(nil)
var _ Node = (*BreakStmt)(nil)
var _ Node = (*ContinueStmt)(nil)
var _ Node = (*ConstNode)(nil)
var _ Node = (*StructDecl)(nil)
var _ Node = (*Objects)(nil)
var _ Node = (*SelfOpStmt)(nil)
var _ Node = (*SwitchNode)(nil)
var _ Node = (*CaseNode)(nil)
var _ Node = (*DefaultNode)(nil)
var _ Node = (*MethodNode)(nil)
var _ Node = (*AutoFreeNode)(nil)
var _ Node = (*EnumDecl)(nil)
var _ Node = (*IndexExpr)(nil)
var _ Node = (*GenericInstantiation)(nil)
var _ Node = (*Dereference)(nil)

var _ codeBlockIface = (*FuncNode)(nil)
var _ codeBlockIface = (*IfNode)(nil)
var _ codeBlockIface = (*ElseNode)(nil)
var _ codeBlockIface = (*ForNode)(nil)
var _ codeBlockIface = (*SwitchNode)(nil)
var _ codeBlockIface = (*MethodNode)(nil)

var _ FuncNameNode = (*Object)(nil)
var _ FuncNameNode = (*Objects)(nil)

var _ astdata.Typ = (*Object)(nil)
var _ astdata.Typ = (*Objects)(nil)
var _ astdata.Typ = (*ContinuityType)(nil)
var _ astdata.Typ = (*GenericInstantiation)(nil)

var _ Expr = (*Object)(nil)
var _ Expr = (*Objects)(nil)
var _ Expr = (*CallNode)(nil)
var _ Expr = (*OpExpr)(nil)
var _ Expr = (*IndexExpr)(nil)
var _ Expr = (*Dereference)(nil)

var _ set_nosemicolon_interface = (*ASSIGNNode)(nil)
var _ set_nosemicolon_interface = (*SelfOpStmt)(nil)
var _ set_nosemicolon_interface = (*SelfOpStmt)(nil)
var _ set_nosemicolon_interface = (*CallNode)(nil)

type set_nosemicolon_interface interface {
	SetNosemicolon(nosemicolon bool)
}

// CDecl 表示一个支持生成C头文件的一个声明语句的类型
type CDecl interface {
	Node
	CDecl(buf *strings.Builder)
}

// 变量声明节点
type VarNode struct {
	TYPE  astdata.Typ //变量类型
	Value Expr        //值
	Name  string      //变量名
	CType string
	//后两个用于出错时报错
	FileName    string
	LineNum     int
	IsFunc      bool
	nosemicolon bool
}

// NewVarNode 创建变量声明节点
func NewVarNode(name string, Type astdata.Typ, IsFunc bool, FileName string, LineNum int) *VarNode {
	return &VarNode{Name: name, TYPE: Type, IsFunc: IsFunc, FileName: FileName, LineNum: LineNum}
}

func (n *VarNode) String() string {
	var buf strings.Builder
	if n == nil {
		buf.WriteString("&ast.VarNode{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.VarNode")
		buf.WriteString(fmt.Sprintf("%+v", *n))
	}
	return buf.String()
}

func (n *VarNode) SetNosemicolon(nosemicolon bool) {
	n.nosemicolon = nosemicolon
}

func (v *VarNode) C(buf *strings.Builder) {
	if v.CType == "" {
		tocVarNode(v)
	}
	buf.Grow(65)
	buf.WriteString(v.CType)
	buf.WriteString(" ")
	buf.WriteString(v.Name)
	if v.IsFunc && v.Value != nil { //是局部变量初始化
		buf.WriteString(" = ")
		v.Value.C(buf)
	}
	if !v.nosemicolon {
		buf.WriteString(" ;")
	}
}

func (v *VarNode) CDecl(buf *strings.Builder) {
	tocVarNode(v)
	buf.Grow(65)
	buf.WriteString("extern ")
	buf.WriteString(v.CType)
	buf.WriteString(" ")
	buf.WriteString(v.Name)
	buf.WriteString(" ;")
}

func tocVarNode(n *VarNode) {
	typ := n.TYPE.Typ()
	if typ[0] == '[' { //如果是连续类型
		elem, Len := new(strings.Builder), new(strings.Builder)
		splitElemAndLen(elem, Len, typ)
		n.Name, n.CType = n.Name+Len.String(), typeToC(elem.String())
	} else {
		n.CType = typeToC(typ)
	}
}

// splitElemAndLen 分割元素类型与长度
// 对于单维数组 [expr]x elem写入 x Len 写入 [expr]
// 对于多维数组 [expr]x elem写入 x Len 写入 所有的[expr]
func splitElemAndLen(elem, Len *strings.Builder, typ string) {
	if typ[0] == '[' {
		e, l, _ := utils.Elem(typ)
		Len.WriteString(l)
		splitElemAndLen(elem, Len, e)
		return
	}
	elem.WriteString(typ)
}

// 函数节点
type FuncNode struct {
	codeBlock
	*FuncInfo
}

// NewFuncNode 创建函数节点
func NewFuncNode(info *FuncInfo) *FuncNode {
	var ret FuncNode
	ret.FuncInfo = info
	ret.codeBlock = newCodeBlock()
	return &ret
}

func (f *FuncNode) String() string {
	var buf strings.Builder
	if f == nil {
		buf.WriteString("&ast.FuncNode{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.FuncNode{\n")
		buf.WriteString(fmt.Sprintf("name=%s\t", f.Name))
		buf.WriteString(fmt.Sprintf("Parame=%s\t", f.Parame))
		buf.WriteString(fmt.Sprintf("RetValue=%s\t", f.RetValue))
		buf.WriteString(fmt.Sprintf("TypeParame=%s\n", f.TypeParame))
		buf.WriteString(fmt.Sprintf("left=%d\tright=%d\t", f.Left, f.Right))
		buf.WriteString(fmt.Sprintf("len=%d\n", f.Right-f.Left))
		buf.WriteString(f.Sbt.String())
	}
	return buf.String()
}

func (f *FuncNode) C(buf *strings.Builder) {
	buf.Grow(100)
	if f.Name == "main" {
		buf.WriteString("int main(){\n")
		buf.WriteString("main__init();\n")
	} else {
		if len(f.RetValue) != 0 {
			buf.WriteString(typeToC(f.RetValue[0].Type.Typ()))
		} else {
			buf.WriteString("void")
		}
		buf.WriteString(" ")
		buf.WriteString(f.Name)
		buf.WriteString("(")
		plen := len(f.Parame)
		for i := 0; i < plen; i++ {
			buf.WriteString(typeToC(f.Parame[i].Type.Typ()))
			buf.WriteString(" ")
			buf.WriteString(f.Parame[i].Name)
			if i+1 < plen {
				buf.WriteString(",")
			}
		}
		buf.WriteString("){")
	}
}

func (f *FuncNode) CDecl(buf *strings.Builder) {
	if f.TypeParame != nil {
		return
	}
	buf.Grow(100)
	if f.Name == "main" {
		buf.WriteString("int main();\n")
		return
	}
	if len(f.RetValue) != 0 {
		buf.WriteString(typeToC(f.RetValue[0].Type.Typ()))
	} else {
		buf.WriteString("void")
	}
	buf.WriteString(" ")
	buf.WriteString(f.Name)
	buf.WriteString("(")
	plen := len(f.Parame)
	for i := 0; i < plen; i++ {
		buf.WriteString(typeToC(f.Parame[i].Type.Typ()))
		buf.WriteString(" ")
		buf.WriteString(f.Parame[i].Name)
		if i+1 < plen {
			buf.WriteString(",")
		}
	}
	buf.WriteString(");")
}

// 赋值节点
type AssignmentNode struct {
	//目的操作数，源操作数
	Dest        Expr
	Src         Expr
	nosemicolon bool
}

type ASSIGNNode = AssignmentNode

// NewASSIGNNode 创建赋值节点
func NewASSIGNNode(Dest Expr, Src Expr) *ASSIGNNode {
	return &ASSIGNNode{
		Dest: Dest,
		Src:  Src,
	}
}

func (a *ASSIGNNode) String() string {
	var buf strings.Builder
	if a == nil {
		buf.WriteString("&ast.ASSIGNode{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.ASSIGNode{")
		buf.WriteString("\nDest:")
		buf.WriteString(a.Dest.String())
		buf.WriteString("\nSrc:")
		buf.WriteString(a.Src.String())
		buf.WriteString("\n\t}")
	}
	return buf.String()
}

func (a *ASSIGNNode) C(buf *strings.Builder) {
	buf.Grow(50)
	a.Dest.C(buf)
	buf.WriteString(" = ")
	a.Src.C(buf)
	if !a.nosemicolon {
		buf.WriteString(" ;")
	}
}

func (a *ASSIGNNode) SetNosemicolon(nosemicolon bool) {
	a.nosemicolon = nosemicolon
}

// 对象节点
//
// 可能表示
//   - 整数
//   - 浮点数
//   - 布尔值
//   - 符号
//   - 字符串
type Object struct {
	Name string
	Kind ObjKind
}

// 创建对象节点
func NewObject(Kind ObjKind, Name string) *Object {
	ret := &Object{Name: Name}
	ret.Kind = Kind
	return ret
}

func (o *Object) String() string {
	var buf strings.Builder
	if o == nil {
		buf.WriteString("&ast.Object{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.Object")
		buf.WriteString(fmt.Sprintf("%+v", *o))
	}
	return buf.String()
}

func (o *Object) FuncName() string { return o.Name }

func (o *Object) Typ() string { return o.Name }

func (o *Object) SetTyp() { o.Kind |= TypeObj }

func (o *Object) Copy() astdata.Typ {
	ret := *o
	return &ret
}

func (o *Object) SetLea(i int) {
	n, leai := utils.Ret_type_no_lea(o.Name)
	if leai == i {
		return
	}
	o.Kind |= LeaObj
	var buf strings.Builder
	buf.Grow(i + len(n))
	buf.WriteString(strings.Repeat("&", i))
	buf.WriteString(n)
	o.Name = buf.String()
}

func (o *Object) C(buf *strings.Builder) {
	buf.Grow(len(o.Name))
	switch o.Kind {
	case INTOBJ, FLOATOBJ, BoolObj, StringObj, SymbolObj, StructPtr, StructPtr | SymbolObj, SymbolObj | EnumObj, TypeObj:
		buf.WriteString(o.Name)
	case LeaObj, LeaObj | StructPtr:
		buf.WriteString("&")
		buf.WriteString(o.Name)
	case DerefObj, DerefObj | StructPtr:
		buf.WriteString("(*")
		buf.WriteString(o.Name)
		buf.WriteString(")")
	case NilObj:
		buf.WriteString("NULL")
	}
}

func (o *Object) CType(buf *strings.Builder) {
	switch o.Kind {
	case INTOBJ, FLOATOBJ, BoolObj, StringObj, SymbolObj, StructPtr, StructPtr | SymbolObj, SymbolObj | EnumObj, TypeObj:
		buf.WriteString(typeToC(o.Name))
	case LeaObj, LeaObj | StructPtr:
		buf.WriteString(typeToC(o.Name))
		buf.WriteString("*")
	case DerefObj, DerefObj | StructPtr:
		buf.WriteString("(*")
		buf.WriteString(typeToC(o.Name))
		buf.WriteString(")")
	case NilObj:
		buf.WriteString("NULL")
	}
}

func (o *Object) expr() {}

// 运算表达式节点
type OperationExpr struct {
	Src1    Expr
	Src2    Expr
	OP      enum.OPSymbol
	IsStr   bool //是否是字符串类型，由check处理
	Inparen bool //是否在小括号内
}

// 运算表达式节点
type OpExpr = OperationExpr

// NewOpExpr 创建运算表达式节点
func NewOpExpr(OP enum.OPSymbol, Src1, Src2 Expr) *OpExpr {
	return &OpExpr{
		OP:   OP,
		Src1: Src1,
		Src2: Src2,
	}
}

func (a *OpExpr) String() string {
	var buf strings.Builder
	buf.Grow(10)
	if a == nil {
		buf.WriteString("&ast.OpExpr{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.OpExpr{")
		buf.WriteString("\nOP:")
		buf.WriteString(a.OP.String())
		buf.WriteString("\nSrc1:")
		buf.WriteString(a.Src1.String())
		buf.WriteString("\nSrc2:")
		buf.WriteString(a.Src2.String())
		buf.WriteString("\nInparen:")
		buf.WriteString(strconv.FormatBool(a.Inparen))
		buf.WriteString("}")
	}
	return buf.String()
}

func (a *OpExpr) expr() {

}

func (a *OpExpr) C(buf *strings.Builder) {
	buf.Grow(10)
	if a.Inparen {
		buf.WriteString("(")
		defer buf.WriteString(")")
	}
	// if a.OP == enum.EqualOP && a.IsStr {
	// 	bol := NewOpExpr(enum.EqualOP, Num0, NewCallExpr(strcmp, a.Src1, a.Src2))
	// 	bol.C(buf)
	// 	return
	// }
	a.Src1.C(buf)
	str, ok := opToStr[a.OP]
	if !ok {
		panic(fmt.Errorf("未知的 op: %s", a.OP.String()))
	}
	buf.WriteString(str)
	a.Src2.C(buf)
}

var strcmp = NewObject(SymbolObj, "strcmp")

var Num0 = NewObject(INTOBJ, "0")

var opToStr = map[enum.OPSymbol]string{
	enum.ADDOP:      " + ",
	enum.SUBOP:      " - ",
	enum.MULOP:      " * ",
	enum.DIVOP:      " / ",
	enum.LessOP:     " < ",
	enum.GreaterOP:  " > ",
	enum.EqualOP:    " == ",
	enum.NoEqualOP:  " != ",
	enum.RemainOP:   " % ",
	enum.IncOP:      "++",
	enum.DecOP:      "--",
	enum.AndOP:      "&",
	enum.OrOP:       "|",
	enum.XorOp:      "^",
	enum.LogicAndOP: "&&",
	enum.LogicOrOP:  "||",
}

// 右大括号节点
type RbraceNode struct{}

func NewRbraceNode() RbraceNode {
	return RbraceNode{}
}

func (b RbraceNode) String() string {
	var buf strings.Builder
	buf.WriteString("&ast.RbraceNode{}")
	return buf.String()
}

func (b RbraceNode) C(buf *strings.Builder) {
	buf.WriteString("}")
}

// if节点
type IfNode struct {
	codeBlock
	BoolExpr Expr
}

// NewIfNode 创建if节点
func NewIfNode() *IfNode {
	ret := &IfNode{}
	ret.codeBlock = newCodeBlock()
	return ret
}

func (l *IfNode) String() string {
	var buf strings.Builder
	if l == nil {
		buf.WriteString("&ast.IfNode{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.IfNode{\n")
		buf.WriteString(fmt.Sprintf("left=%d\tright=%d\t", l.Left, l.Right))
		buf.WriteString(fmt.Sprintf("len=%d\n", l.Right-l.Left))
		buf.WriteString(l.BoolExpr.String())
		buf.WriteString(l.Sbt.String())
	}
	return buf.String()
}

func (l *IfNode) C(buf *strings.Builder) {
	buf.Grow(7)
	buf.WriteString("if (")
	l.BoolExpr.C(buf)
	buf.WriteString("){")
}

// else节点
type ElseNode struct {
	codeBlock
	BoolExpr Expr
}

// NewElseNode 创建else节点
func NewElseNode() *ElseNode {
	ret := &ElseNode{}
	ret.codeBlock = newCodeBlock()
	return ret
}

func (l *ElseNode) String() string {
	var buf strings.Builder
	if l == nil {
		buf.WriteString("&ast.ElseNode{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.ElseNode{\n")
		buf.WriteString(fmt.Sprintf("left=%d\tright=%d\t", l.Left, l.Right))
		buf.WriteString(fmt.Sprintf("len=%d\n", l.Right-l.Left))
		if l.BoolExpr != nil {
			buf.WriteString(fmt.Sprintf("boolexpr=%+v\n", l.BoolExpr))
		}
		buf.WriteString(l.Sbt.String())
	}
	return buf.String()
}

func (l *ElseNode) C(buf *strings.Builder) {
	buf.Grow(13)
	buf.WriteString("else ")
	if l.BoolExpr != nil {
		buf.WriteString("if (")
		l.BoolExpr.C(buf)
		buf.WriteString(")")
	}
	buf.WriteString("{\n")
}

// codeBlock 是代码块应该包含的值和方法
type codeBlock struct {
	Sbt   *Sbt //当前作用域符号表
	Left  int  //第一个节点偏移量
	Right int  //右大括号偏移量
}

func newCodeBlock() codeBlock {
	ret := codeBlock{}
	ret.Sbt = NewSbt(false)
	return ret
}

func (c *codeBlock) getLeft() *int {
	return &c.Left
}

func (c *codeBlock) getRight() *int {
	return &c.Right
}

func (c *codeBlock) getSbt() *Sbt {
	return c.Sbt
}

// codeBlockIface 是代码块节点接口
type codeBlockIface interface {
	Node
	getLeft() *int
	getRight() *int
	getSbt() *Sbt
}

// for节点
type ForNode struct {
	codeBlock
	InitStmt Node
	BoolExpr Expr
	EndStmt  Node
}

// NewForNode 创建for节点
func NewForNode() *ForNode {
	ret := &ForNode{}
	ret.codeBlock = newCodeBlock()
	return ret
}

func (l *ForNode) String() string {
	var buf strings.Builder
	if l == nil {
		buf.WriteString("&ast.ForNode{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.ForNode{\n")
		buf.WriteString(fmt.Sprintf("left=%d\tright=%d\t", l.Left, l.Right))
		buf.WriteString(fmt.Sprintf("len=%d", l.Right-l.Left))
		if l.InitStmt != nil {
			buf.WriteString("\nInitStmt:")
			buf.WriteString(l.InitStmt.String())
		}
		if l.BoolExpr != nil {
			buf.WriteString("\nBoolStmt:")
			buf.WriteString(l.BoolExpr.String())
		}
		if l.EndStmt != nil {
			buf.WriteString("\nEndStmt:")
			buf.WriteString(l.EndStmt.String())
		}
		buf.WriteString(l.Sbt.String())
	}
	return buf.String()
}

func (l *ForNode) C(buf *strings.Builder) {
	buf.Grow(11)
	buf.WriteString("for (")
	if l.InitStmt != nil {
		l.InitStmt.(set_nosemicolon_interface).SetNosemicolon(true)
		l.InitStmt.C(buf)
	}
	buf.WriteString(" ;")
	if l.BoolExpr != nil {
		l.BoolExpr.C(buf)
	}
	buf.WriteString(";")
	if l.EndStmt != nil {
		iface := l.EndStmt.(set_nosemicolon_interface)
		iface.SetNosemicolon(true)
		l.EndStmt.C(buf)
	}
	buf.WriteString("){")
}

// 函数调用节点
type CallNode struct {
	FuncName      FuncNameNode //调用函数名
	Parame        []Expr       //Parameter
	CCallFuncName string
	InAutoFree    bool
	nosemicolon   bool
}

// NewCallNode 创建函数调用节点
func NewCallExpr(funcname FuncNameNode, InAutoFree bool, parame ...Expr) *CallNode {
	ret := new(CallNode)
	ret.FuncName = funcname
	ret.Parame = parame
	ret.InAutoFree = InAutoFree
	ret.nosemicolon = true
	return ret
}

func (a *CallNode) String() string {
	var buf strings.Builder
	buf.WriteString("&ast.CallNode")
	if a == nil {
		buf.WriteString("<nil>")
	} else {
		buf.WriteString(fmt.Sprintf("%+v", *a))
	}
	buf.WriteString("}")
	return buf.String()
}

func (c *CallNode) expr() {}

func (c *CallNode) SetNosemicolon(nosemicolon bool) {
	c.nosemicolon = nosemicolon
}

func (a *CallNode) C(buf *strings.Builder) {
	a = utoCCall(a)
	buf.Grow(60)
	defer func() {
		if !a.nosemicolon {
			buf.WriteString(";")
		}
	}()
	pl := len(a.Parame)
	switch a.CCallFuncName {
	case enum.Malloc:
		buf.WriteString("(")
		a.Parame[0].(CType).CType(buf)
		buf.WriteString("*)malloc(sizeof(")
		a.Parame[0].(CType).CType(buf)
		buf.WriteString("))")
		return
	case enum.Int, enum.Float:
		buf.WriteString("(")
		buf.WriteString(typeToC(a.CCallFuncName))
		buf.WriteString(")")
		a.Parame[0].C(buf)
		return
	case enum.UnsafeAdd:
		buf.WriteString("(((void*)")
		a.Parame[0].C(buf)
		buf.WriteString(")+")
		a.Parame[1].C(buf)
		buf.WriteString(")")
		return
	case enum.UnsafeConvert:
		buf.WriteString("(")
		a.Parame[1].(CType).CType(buf)
		buf.WriteString(")")
		a.Parame[0].C(buf)
		return
	case enum.MallocSize:
		buf.WriteString("malloc(")
		a.Parame[0].C(buf)
		buf.WriteString(")")
		return
	case enum.UnsafeSizeof:
		buf.WriteString("sizeof(")
		a.Parame[0].(CType).CType(buf)
		buf.WriteString(")")
		return
	case enum.MemPoolNew:
		buf.WriteString(enum.MemPoolNew)
		buf.WriteString("(")
		a.Parame[0].C(buf)
		buf.WriteString(",")
		if o, ok := a.Parame[1].(*Object); ok && o.Kind == TypeObj { //如果是类型
			buf.WriteString("sizeof(")
			buf.WriteString(typeToC(o.Name))
			buf.WriteString(")")
		} else {
			a.Parame[1].C(buf)
		}
		buf.WriteString(")")
		return
	case enum.UnsafePointer:
		buf.WriteString("(void *)")
		a.Parame[0].C(buf)
		return
	}
	buf.WriteString(a.CCallFuncName)
	buf.WriteString("(")
	for i := 0; i < pl; i++ {
		a.Parame[i].C(buf)
		if i+1 < pl { //如果不是最后一个参数
			buf.WriteString(",")
		}
	}
	buf.WriteString(")")
}

// utoCCall 将调用节点转换为cast等价的
// - c是被转换的，不能为nil
func utoCCall(c *CallNode) *CallNode {
	var funcname string
	var parame []Expr
	poff := 0
	if n, ok := c.FuncName.(*Objects); ok {
		if c.InAutoFree {
			poff = 1
		}
		if n.T != "" { //如果是方法
			poff++
			parame = make([]Expr, len(c.Parame)+1)
			funcname = astdata.Generate_method_symbol(n.T, n.Slice[len(n.Slice)-1].Name)
			receiver := *n
			receiver.Slice = n.Slice[:len(n.Slice)-1]
			parame[poff-1] = &receiver
		} else {
			parame = make([]Expr, len(c.Parame))
			var buf strings.Builder
			buf.WriteString(n.Slice[0].Name)
			for _, v := range n.Slice[1:] {
				buf.WriteString(enum.PackageSep)
				buf.WriteString(v.Name)
			}
			funcname = buf.String()
		}
	} else {
		parame = make([]Expr, len(c.Parame))
		funcname = c.FuncName.FuncName()
	}
	c.CCallFuncName = funcname
	for i := 0; i < len(c.Parame); i++ {
		if parame[i] != nil {
			continue
		}
		parame[i] = c.Parame[i]
	}
	c.Parame = parame
	return c
}

// return节点
type ReturnNode struct {
	RetValue Expr
}

// NewReturnNode 创建return节点
func NewReturnNode() *ReturnNode {
	return &ReturnNode{}
}

func (l *ReturnNode) String() string {
	var buf strings.Builder
	if l == nil {
		buf.WriteString("&ast.ReturnNode{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.ReturnNode{")
		buf.WriteString(fmt.Sprint(l.RetValue))
		buf.WriteString("}")
	}
	return buf.String()
}

func (l *ReturnNode) C(buf *strings.Builder) {
	buf.Grow(8)
	buf.WriteString("return ")
	if l.RetValue != nil {
		l.RetValue.C(buf)
	}
	buf.WriteString(";")
}

// 缩写： statement 缩写成Stmt

// goto语句
type GotoStmt struct {
	Label string
}

func NewGotoStmt(Label string) *GotoStmt {
	return &GotoStmt{Label: Label}
}

func (g *GotoStmt) String() string {
	return fmt.Sprintf("&ast.GotoStmt{Label:%s}", g.Label)
}

func (g *GotoStmt) C(buf *strings.Builder) {
	buf.Grow(len(g.Label) + 6)
	buf.WriteString("goto ")
	buf.WriteString(g.Label)
	buf.WriteString(";")
}

// 标签
type LabelNode struct {
	Value string
}

func NewLabelNode(value string) *LabelNode {
	return &LabelNode{Value: value}
}

func (b *LabelNode) String() string {
	return fmt.Sprintf("&ast.LabelNode{Value:%s}", b.Value)
}

func (l *LabelNode) C(buf *strings.Builder) {
	buf.Grow(len(l.Value) + 1)
	buf.WriteString(l.Value)
	buf.WriteString(":")
}

// break语句
type BreakStmt struct{}

func NewBreakStmt() BreakStmt {
	return BreakStmt{}
}

func (b BreakStmt) String() string {
	var buf strings.Builder
	buf.WriteString("&ast.BreakStmt{}\n}")
	return buf.String()
}

func (b BreakStmt) C(buf *strings.Builder) {
	buf.Grow(7)
	buf.WriteString("break ;")
}

// continue语句
type ContinueStmt struct{}

func NewContinueStmt() ContinueStmt {
	return ContinueStmt{}
}

func (c ContinueStmt) String() string {
	var buf strings.Builder
	buf.WriteString("&ast.ContinueStmt{}\n}")
	return buf.String()
}

func (c ContinueStmt) C(buf *strings.Builder) {
	buf.Grow(10)
	buf.WriteString("continue ;")
}

// 常量声明节点
type ConstNode struct {
	TYPE  astdata.Typ
	Value Expr
	Name  string
}

// NewConstNode 创建常量声明节点
func NewConstNode(name string, Type astdata.Typ) *ConstNode {
	return &ConstNode{Name: name, TYPE: Type}
}

func (n *ConstNode) String() string {
	var buf strings.Builder
	if n == nil {
		buf.WriteString("&ast.Const{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.Const")
		buf.WriteString(fmt.Sprintf("%+v", *n))
	}
	return buf.String()
}

func (c *ConstNode) C(buf *strings.Builder) {
	var typename string
	if o, ok := c.TYPE.(*Object); ok {
		typename = typeToC(o.Name)
	} else {
		typename = c.TYPE.Typ()
	}
	buf.Grow(60)
	buf.WriteString(enum.Const)
	buf.WriteString(" ")
	buf.WriteString(typename)
	buf.WriteString(" ")
	buf.WriteString(c.Name)
	if c.Value == nil { //没有初始化
		buf.WriteString(" ;")
		return
	}
	buf.WriteString(" = ")
	c.Value.C(buf)
	buf.WriteString(" ;")
}

func (c *ConstNode) CDecl(buf *strings.Builder) {
	buf.WriteString("extern ")
	var typename string
	if o, ok := c.TYPE.(*Object); ok {
		typename = typeToC(o.Name)
	} else {
		typename = c.TYPE.Typ()
	}
	buf.Grow(60)
	buf.WriteString(enum.Const)
	buf.WriteString(" ")
	buf.WriteString(typename)
	buf.WriteString(" ")
	buf.WriteString(c.Name)
	buf.WriteString(" ;")
}

// StructDecl 结构体声明
//
// 缩写：struct declaration 缩写成：StructDecl
type StructDecl struct {
	sbt        *Sbt
	Name       string
	FileName   string
	FieldTable []Field
	LineNum    int
	TypeParame []astdata.NameAndType
	InFunc     bool
}

func (s *StructDecl) String() string {
	var buf strings.Builder
	if s == nil {
		buf.WriteString("&ast.StructDecl{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.StructDecl")
		buf.WriteString(fmt.Sprintf("%+v", *s))
	}
	return buf.String()
}

func (s *StructDecl) C(buf *strings.Builder) {
	if !s.InFunc { //全局结构体的C代码由CDecl生产
		return
	}
	s.c(buf)
}

func (s *StructDecl) c(buf *strings.Builder) {
	if s.TypeParame != nil { //跳过未实例化泛型
		return
	}
	buf.Grow(20 + len(s.FieldTable)*15)
	buf.WriteString("typedef struct ")
	buf.WriteString(s.Name)
	buf.WriteString("{\n")
	for _, v := range s.FieldTable {
		buf.WriteString(typeToC(v.Type.Typ()))
		buf.WriteString(" ")
		buf.WriteString(v.Name)
		buf.WriteString(";\n")
	}
	buf.WriteString("}")
	buf.WriteString(s.Name)
	buf.WriteString(";")
}

func (s *StructDecl) CDecl(buf *strings.Builder) {
	s.c(buf)
}

func (s *StructDecl) genName() string {
	list := typInfoToStr(s.FieldTable)
	return utils.GenerateGenericTypes(s.Name, list)
}

// FindField 寻找结构体字段中是否有Name
// 返回值Field.Name==""表示结构体字段中没有要查询到
func (info *StructDecl) FindField(Name string) Field {
	for _, v := range info.FieldTable {
		if v.Name == Name {
			return v
		}
	}
	return Field{}
}

func (info *StructDecl) My() string {
	return info.Name
}

func (info *StructDecl) DepLen() int {
	return len(info.FieldTable)
}

func (info *StructDecl) Dep(i int) data.IsItARecursiveType {
	iface := fieldInfo{typ: info.FieldTable[i].Type}
	iface.dep = findTypeDep(info.sbt, info.FieldTable[i].Type)
	return iface
}

func typInfoToStr(typ []astdata.NameAndType) []string {
	copys := make([]string, len(typ))
	for i := 0; i < len(typ); i++ {
		copys[i] = typ[i].Type.Typ()
	}
	return copys
}

func typeToC(typ string) string {
	switch typ {
	case enum.String:
		return "char*"
	case enum.Int:
		return "int64_t"
	case enum.UnsafePointer:
		return "void*"
	}
	switch typ[0] {
	case '&':
		return typeToC(typ[1:]) + "*"
	}
	return typ
}

type Field = astdata.NameAndType

type Objects struct {
	T              string
	Slice          []*Object
	IsImportSymbol bool //是否是导入符号,由语义检查填充
}

func NewObjects(slice []*Object) *Objects {
	return &Objects{Slice: slice}
}

func (o *Objects) String() string {
	var buf strings.Builder
	if o == nil {
		buf.WriteString("&ast.Objects{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.Objects{")
		for _, v := range o.Slice {
			buf.WriteString(v.String())
		}
		buf.WriteString("}")
	}
	return buf.String()
}

func (o *Objects) FuncName() string {
	var buf strings.Builder
	buf.Grow(50)
	for _, v := range o.Slice[:len(o.Slice)-1] {
		buf.WriteString(v.Name)
		buf.WriteString(".")
	}
	buf.WriteString(o.Slice[len(o.Slice)-1].Name)
	return buf.String()
}

func (o *Objects) Typ() string {
	var buf strings.Builder
	buf.Grow(50)
	if o.Slice[0].Kind&LeaObj != 0 {
		buf.WriteString("&")
	}
	buf.WriteString(o.Slice[0].Name)
	buf.WriteString(enum.PackageSep)
	buf.WriteString(o.Slice[1].Name)
	return buf.String()
}

func (o *Objects) SetTyp() { o.Slice[0].Kind |= TypeObj }

func (o *Objects) Copy() astdata.Typ {
	ret := *o
	return &ret
}

func (o *Objects) SetLea(i int) {
	o.Slice[0].SetLea(i)
}

func (o *Objects) C(buf *strings.Builder) {
	buf.Grow(50)
	slen := len(o.Slice)
	for i := 0; i < slen; i++ {
		o.Slice[i].C(buf)
		if i+1 < slen {
			if o.Slice[i].Kind&StructPtr != 0 && o.Slice[i].Kind&DerefObj == 0 {
				buf.WriteString("->")
			} else {
				if o.IsImportSymbol || o.Slice[i].Kind&EnumObj != 0 {
					buf.WriteString(enum.PackageSep)
				} else {
					buf.WriteString(".")
				}
			}
		}
	}
}

func (o *Objects) CType(buf *strings.Builder) {
	buf.Grow(20)
	buf.WriteString(o.Slice[0].Name)
	buf.WriteString(enum.PackageSep)
	buf.WriteString(o.Slice[1].Name)
}

func (o *Objects) expr() {}

// 自操作语句
// 缩写： Self-operating statement 缩写成 SelfOpStmt
// 源操作数只可能是下列类型
//   - 对象节点 [ast.Object]
type SelfOpStmt struct {
	Dest        Expr
	OP          enum.OPSymbol
	nosemicolon bool
}

func NewSelfOpStmt(OP enum.OPSymbol, Dest Expr) *SelfOpStmt {
	return &SelfOpStmt{OP: OP, Dest: Dest}
}

func (o *SelfOpStmt) String() string {
	var buf strings.Builder
	if o == nil {
		buf.WriteString("&ast.SelfOpStmt{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.SelfOpStmt")
		buf.WriteString(fmt.Sprintf("%+v", *o))
	}
	return buf.String()
}

func (o *SelfOpStmt) C(buf *strings.Builder) {
	buf.Grow(10)
	o.Dest.C(buf)
	buf.WriteString(opToStr[o.OP])
	if !o.nosemicolon {
		buf.WriteString(";")
	}
}

func (o *SelfOpStmt) SetNosemicolon(nosemicolon bool) {
	o.nosemicolon = nosemicolon
}

// switch节点
type SwitchNode struct {
	codeBlock
	Expr Expr
}

func NewSwitchNode() *SwitchNode {
	ret := &SwitchNode{}
	ret.codeBlock = newCodeBlock()
	return ret
}

func (s *SwitchNode) String() string {
	var buf strings.Builder
	if s == nil {
		buf.WriteString("&ast.SwitchNode{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.SwitchNode")
		buf.WriteString(fmt.Sprintf("%+v", *s))
	}
	return buf.String()
}

func (s *SwitchNode) C(buf *strings.Builder) {
	buf.Grow(10)
	buf.WriteString("switch (")
	s.Expr.C(buf)
	buf.WriteString("){")
}

// case节点
type CaseNode struct {
	Expr  Expr
	Sbt   *Sbt
	Left  int
	Right int
}

func NewCaseNode() *CaseNode {
	return &CaseNode{Sbt: NewSbt(false)}
}

func (c *CaseNode) String() string {
	var buf strings.Builder
	if c == nil {
		buf.WriteString("&ast.CaseNode{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.CasehNode")
		buf.WriteString(fmt.Sprintf("%+v", *c))
	}
	return buf.String()
}

func (c *CaseNode) C(buf *strings.Builder) {
	buf.Grow(10)
	buf.WriteString("case ")
	c.Expr.C(buf)
	buf.WriteString(":")
}

// defaultcase节点
type DefaultNode struct {
	Sbt   *Sbt
	Left  int
	Right int
}

func NewDefaultNode() *DefaultNode {
	return &DefaultNode{Sbt: NewSbt(false)}
}

func (d *DefaultNode) String() string {
	var buf strings.Builder
	if d == nil {
		buf.WriteString("&ast.DefaultNode{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.DefaultNode")
		buf.WriteString(fmt.Sprintf("%+v", *d))
	}
	return buf.String()
}

func (c *DefaultNode) C(buf *strings.Builder) {
	buf.Grow(10)
	buf.WriteString("default :")
}

// MethodNode 方法节点
type MethodNode struct {
	codeBlock
	*FuncInfo
	Typ string
}

// NewMethodNode 创建函数节点
func NewMethodNode(typ string, info *FuncInfo) *MethodNode {
	ret := &MethodNode{Typ: typ, FuncInfo: info}
	ret.codeBlock = newCodeBlock()
	return ret
}

func (m *MethodNode) String() string {
	var buf strings.Builder
	if m == nil {
		buf.WriteString("&ast.MethodNode{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.MethodNode{\n")
		buf.WriteString(fmt.Sprintf("type=%s\t", m.Typ))
		buf.WriteString(fmt.Sprintf("funcinfo=%s\t", m.FuncInfo.String()))
		buf.WriteString(fmt.Sprintf("left=%d\tright=%d\t", m.Left, m.Right))
		buf.WriteString(fmt.Sprintf("len=%d\n", m.Right-m.Left))
		buf.WriteString(m.Sbt.String())
	}
	return buf.String()
}

func (m *MethodNode) C(buf *strings.Builder) {
	//Note:依赖CDecl在之前被调用
	f := FuncNode{FuncInfo: m.FuncInfo}
	f.C(buf)
}

func (m *MethodNode) CDecl(buf *strings.Builder) {
	m.Name = astdata.Generate_method_symbol(m.Typ, m.FuncInfo.Name)
	f := FuncNode{FuncInfo: m.FuncInfo}
	f.CDecl(buf)
}

// 自动释放块节点
type AutoFreeNode struct {
	codeBlock
	Expr     Expr
	FileName string
}

func NewAutoFreeNode(FileName string) *AutoFreeNode {
	ret := &AutoFreeNode{FileName: FileName}
	ret.codeBlock = newCodeBlock()
	return ret
}

func (a *AutoFreeNode) String() string {
	var buf strings.Builder
	if a == nil {
		buf.WriteString("&ast.AutoFreeNode{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.AutoFreeNode")
		buf.WriteString(fmt.Sprintf("%+v", *a))
	}
	return buf.String()
}

func (a *AutoFreeNode) C(buf *strings.Builder) {
	tmp := VarNode{Name: utils.Generate_mempool_Name(a.Left, a.FileName), TYPE: mempool, CType: enum.MemPool, Value: NewCallExpr(mempoolNew, true, a.Expr), IsFunc: true}
	tmp.C(buf)
}

var mempoolNew = NewObject(SymbolObj, "mempool__New")

// EnumDecl 枚举声明
type EnumDecl struct {
	Name  string
	Enums []string
}

func NewEnumDecl(Name string) *EnumDecl {
	return &EnumDecl{Name: Name}
}

func (s *EnumDecl) String() string {
	var buf strings.Builder
	if s == nil {
		buf.WriteString("&ast.EnumDecl{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.EnumDecl")
		buf.WriteString(fmt.Sprintf("%+v", *s))
	}
	return buf.String()
}

func (s *EnumDecl) C(buf *strings.Builder) {
	elen := len(s.Enums)
	buf.Grow(20 + elen*10)
	buf.WriteString("typedef enum {")
	for i := 0; i < elen; i++ {
		buf.WriteString(s.Enums[i])
		if i+1 < elen {
			buf.WriteString(",")
		}
	}
	buf.WriteString("} ")
	buf.WriteString(s.Name)
	buf.WriteString(";")
}

func (s *EnumDecl) CDecl(buf *strings.Builder) {
	s.C(buf)
}

// ContinuityType 连续类型
type ContinuityType struct {
	Len  Expr
	TYPE astdata.Typ
	UStr string
}

func NewContinuityType(Len Expr, Type astdata.Typ, UStr string) *ContinuityType {
	return &ContinuityType{Len: Len, TYPE: Type, UStr: UStr}
}

func (c *ContinuityType) String() string {
	var buf strings.Builder
	if c == nil {
		buf.WriteString("&ast.ContinuityType{")
		buf.WriteString("<nil>")
		buf.WriteString("}")
	} else {
		buf.WriteString("&ast.ContinuityType")
		buf.WriteString(fmt.Sprintf("%+v", *c))
	}
	return buf.String()
}

func (c *ContinuityType) SetTyp() {}

func (c *ContinuityType) Copy() astdata.Typ {
	ret := *c
	return &ret
}

func (c *ContinuityType) SetLea(i int) {
	c.TYPE.SetLea(i)
}

func (c *ContinuityType) Typ() string {
	return c.UStr
}

// IndexExpr  索引表达式
// 缩写index expression 缩写成 IndexExpr
type IndexExpr struct {
	X     Expr
	Index Expr
}

func NewIndexExpr(X Expr, Index Expr) *IndexExpr {
	return &IndexExpr{X: X, Index: Index}
}

func (l *IndexExpr) String() string {
	var buf strings.Builder
	if l == nil {
		buf.WriteString("&ast.IndexExpr{<nil>}")
	} else {
		buf.WriteString("&ast.IndexExpr")
		buf.WriteString(fmt.Sprintf("%+v", *l))
	}
	return buf.String()
}

func (l *IndexExpr) C(buf *strings.Builder) {
	buf.Grow(5)
	l.X.C(buf)
	buf.WriteString("[")
	l.Index.C(buf)
	buf.WriteString("]")
}

func (l *IndexExpr) expr() {}

// GenericInstantiation 泛型实例化
type GenericInstantiation struct {
	BaseName   astdata.Typ
	LineNum    int
	ActualType []astdata.Typ
	FileName   string
}

func (g *GenericInstantiation) String() string {
	var buf strings.Builder
	if g == nil {
		buf.WriteString("&ast.GenericInstantiation{<nil>}")
	} else {
		buf.WriteString("&ast.GenericInstantiation{BaseName:")
		buf.WriteString(g.BaseName.Typ())
		fmt.Fprintf(&buf, "\tLineNum:%d\tActualType:", g.LineNum)
		for _, v := range g.ActualType {
			buf.WriteString(v.Typ())
			buf.WriteString(" ")
		}
		buf.WriteString("}")
	}
	return buf.String()
}

func (g *GenericInstantiation) SetTyp() {}

func (g *GenericInstantiation) Typ() string {
	list, havenil := typToStr(g.ActualType)
	if havenil {
		return ""
	}
	return utils.GenerateGenericTypes(g.BaseName.Typ(), list)
}

func (g *GenericInstantiation) C(buf *strings.Builder) {
	panic("不应执行的路径")
}

func typToStr(typ []astdata.Typ) ([]string, bool) {
	list := make([]string, len(typ))
	for i, v := range typ {
		if v == nil {
			return nil, true
		}
		list[i] = v.Typ()
	}
	return list, false
}

func (g *GenericInstantiation) Copy() astdata.Typ {
	ret := *g
	ret.BaseName = g.BaseName.Copy()
	ret.ActualType = copyTyp(ret.ActualType)
	return &ret
}

func copyTyp(typ []astdata.Typ) []astdata.Typ {
	copys := make([]astdata.Typ, len(typ))
	for i, v := range typ {
		copys[i] = v.Copy()
	}
	return copys
}

func copyNameAndTyp(s []astdata.NameAndType) []astdata.NameAndType {
	copys := make([]astdata.NameAndType, len(s))
	for i, v := range s {
		copys[i].Name = v.Name
		copys[i].Type = v.Type.Copy()
	}
	return copys
}

func (g *GenericInstantiation) SetLea(i int) {
	g.BaseName.SetLea(i)
}

func (g *GenericInstantiation) FuncName() string {
	return g.Typ()
}

func (g *GenericInstantiation) expr() {}

// Dereference 解引用节点
type Dereference struct {
	Value Expr
}

func (d *Dereference) String() string {
	var buf strings.Builder
	if d == nil {
		buf.WriteString("&ast.Dereference{<nil>}")
	} else {
		buf.WriteString("&ast.Dereference")
		buf.WriteString(fmt.Sprintf("%+v", *d))
	}
	return buf.String()
}

func (d *Dereference) expr() {}

func (d *Dereference) C(buf *strings.Builder) {
	buf.Grow(5)
	buf.WriteString("*(")
	d.Value.C(buf)
	buf.WriteString(")")
}
